﻿using System;

namespace Mono.Cecil.Metadata
{
	// Token: 0x020000F8 RID: 248
	internal sealed class TableHeapBuffer : HeapBuffer
	{
		// Token: 0x170002B9 RID: 697
		// (get) Token: 0x06000A13 RID: 2579 RVA: 0x00009C40 File Offset: 0x00007E40
		public override bool IsEmpty
		{
			get
			{
				return false;
			}
		}

		// Token: 0x06000A14 RID: 2580 RVA: 0x0002DD84 File Offset: 0x0002BF84
		public TableHeapBuffer(ModuleDefinition module, MetadataBuilder metadata) : base(24)
		{
			this.module = module;
			this.metadata = metadata;
			this.counter = new Func<Table, int>(this.GetTableLength);
		}

		// Token: 0x06000A15 RID: 2581 RVA: 0x0002DDE4 File Offset: 0x0002BFE4
		private int GetTableLength(Table table)
		{
			return (int)this.table_infos[(int)table].Length;
		}

		// Token: 0x06000A16 RID: 2582 RVA: 0x0002DE08 File Offset: 0x0002C008
		public TTable GetTable<TTable>(Table table) where TTable : MetadataTable, new()
		{
			TTable ttable = (TTable)((object)this.tables[(int)table]);
			bool flag = ttable != null;
			TTable result;
			if (flag)
			{
				result = ttable;
			}
			else
			{
				ttable = Activator.CreateInstance<TTable>();
				this.tables[(int)table] = ttable;
				result = ttable;
			}
			return result;
		}

		// Token: 0x06000A17 RID: 2583 RVA: 0x0002DE50 File Offset: 0x0002C050
		public void WriteBySize(uint value, int size)
		{
			bool flag = size == 4;
			if (flag)
			{
				base.WriteUInt32(value);
			}
			else
			{
				base.WriteUInt16((ushort)value);
			}
		}

		// Token: 0x06000A18 RID: 2584 RVA: 0x0002DE7C File Offset: 0x0002C07C
		public void WriteBySize(uint value, bool large)
		{
			if (large)
			{
				base.WriteUInt32(value);
			}
			else
			{
				base.WriteUInt16((ushort)value);
			}
		}

		// Token: 0x06000A19 RID: 2585 RVA: 0x0000598F File Offset: 0x00003B8F
		public void WriteString(uint @string)
		{
			this.WriteBySize(this.string_offsets[(int)@string], this.large_string);
		}

		// Token: 0x06000A1A RID: 2586 RVA: 0x000059A7 File Offset: 0x00003BA7
		public void WriteBlob(uint blob)
		{
			this.WriteBySize(blob, this.large_blob);
		}

		// Token: 0x06000A1B RID: 2587 RVA: 0x000059B8 File Offset: 0x00003BB8
		public void WriteGuid(uint guid)
		{
			this.WriteBySize(guid, this.large_guid);
		}

		// Token: 0x06000A1C RID: 2588 RVA: 0x000059C9 File Offset: 0x00003BC9
		public void WriteRID(uint rid, Table table)
		{
			this.WriteBySize(rid, this.table_infos[(int)table].IsLarge);
		}

		// Token: 0x06000A1D RID: 2589 RVA: 0x0002DEA4 File Offset: 0x0002C0A4
		private int GetCodedIndexSize(CodedIndex coded_index)
		{
			int num = this.coded_index_sizes[(int)coded_index];
			bool flag = num != 0;
			int result;
			if (flag)
			{
				result = num;
			}
			else
			{
				result = (this.coded_index_sizes[(int)coded_index] = coded_index.GetSize(this.counter));
			}
			return result;
		}

		// Token: 0x06000A1E RID: 2590 RVA: 0x000059E5 File Offset: 0x00003BE5
		public void WriteCodedRID(uint rid, CodedIndex coded_index)
		{
			this.WriteBySize(rid, this.GetCodedIndexSize(coded_index));
		}

		// Token: 0x06000A1F RID: 2591 RVA: 0x0002DEE8 File Offset: 0x0002C0E8
		public void WriteTableHeap()
		{
			base.WriteUInt32(0U);
			base.WriteByte(this.GetTableHeapVersion());
			base.WriteByte(0);
			base.WriteByte(this.GetHeapSizes());
			base.WriteByte(10);
			base.WriteUInt64(this.GetValid());
			base.WriteUInt64(55193285546867200UL);
			this.WriteRowCount();
			this.WriteTables();
		}

		// Token: 0x06000A20 RID: 2592 RVA: 0x0002DF54 File Offset: 0x0002C154
		private void WriteRowCount()
		{
			for (int i = 0; i < this.tables.Length; i++)
			{
				MetadataTable metadataTable = this.tables[i];
				bool flag = metadataTable == null || metadataTable.Length == 0;
				if (!flag)
				{
					base.WriteUInt32((uint)metadataTable.Length);
				}
			}
		}

		// Token: 0x06000A21 RID: 2593 RVA: 0x0002DFA8 File Offset: 0x0002C1A8
		private void WriteTables()
		{
			for (int i = 0; i < this.tables.Length; i++)
			{
				MetadataTable metadataTable = this.tables[i];
				bool flag = metadataTable == null || metadataTable.Length == 0;
				if (!flag)
				{
					metadataTable.Write(this);
				}
			}
		}

		// Token: 0x06000A22 RID: 2594 RVA: 0x0002DFF8 File Offset: 0x0002C1F8
		private ulong GetValid()
		{
			ulong num = 0UL;
			for (int i = 0; i < this.tables.Length; i++)
			{
				MetadataTable metadataTable = this.tables[i];
				bool flag = metadataTable == null || metadataTable.Length == 0;
				if (!flag)
				{
					metadataTable.Sort();
					num |= 1UL << i;
				}
			}
			return num;
		}

		// Token: 0x06000A23 RID: 2595 RVA: 0x0002E05C File Offset: 0x0002C25C
		public void ComputeTableInformations()
		{
			bool flag = this.metadata.metadata_builder != null;
			if (flag)
			{
				this.ComputeTableInformations(this.metadata.metadata_builder.table_heap);
			}
			this.ComputeTableInformations(this.metadata.table_heap);
		}

		// Token: 0x06000A24 RID: 2596 RVA: 0x0002E0A8 File Offset: 0x0002C2A8
		private void ComputeTableInformations(TableHeapBuffer table_heap)
		{
			MetadataTable[] array = table_heap.tables;
			for (int i = 0; i < array.Length; i++)
			{
				MetadataTable metadataTable = array[i];
				bool flag = metadataTable != null && metadataTable.Length > 0;
				if (flag)
				{
					this.table_infos[i].Length = (uint)metadataTable.Length;
				}
			}
		}

		// Token: 0x06000A25 RID: 2597 RVA: 0x0002E104 File Offset: 0x0002C304
		private byte GetHeapSizes()
		{
			byte b = 0;
			bool isLarge = this.metadata.string_heap.IsLarge;
			if (isLarge)
			{
				this.large_string = true;
				b |= 1;
			}
			bool isLarge2 = this.metadata.guid_heap.IsLarge;
			if (isLarge2)
			{
				this.large_guid = true;
				b |= 2;
			}
			bool isLarge3 = this.metadata.blob_heap.IsLarge;
			if (isLarge3)
			{
				this.large_blob = true;
				b |= 4;
			}
			return b;
		}

		// Token: 0x06000A26 RID: 2598 RVA: 0x0002E184 File Offset: 0x0002C384
		private byte GetTableHeapVersion()
		{
			TargetRuntime runtime = this.module.Runtime;
			TargetRuntime targetRuntime = runtime;
			byte result;
			if (targetRuntime > TargetRuntime.Net_1_1)
			{
				result = 2;
			}
			else
			{
				result = 1;
			}
			return result;
		}

		// Token: 0x06000A27 RID: 2599 RVA: 0x0002E1B0 File Offset: 0x0002C3B0
		public void FixupData(uint data_rva)
		{
			FieldRVATable table = this.GetTable<FieldRVATable>(Table.FieldRVA);
			bool flag = table.length == 0;
			if (!flag)
			{
				int num = this.GetTable<FieldTable>(Table.Field).IsLarge ? 4 : 2;
				int position = this.position;
				this.position = table.position;
				for (int i = 0; i < table.length; i++)
				{
					uint num2 = base.ReadUInt32();
					this.position -= 4;
					base.WriteUInt32(num2 + data_rva);
					this.position += num;
				}
				this.position = position;
			}
		}

		// Token: 0x04000417 RID: 1047
		private readonly ModuleDefinition module;

		// Token: 0x04000418 RID: 1048
		private readonly MetadataBuilder metadata;

		// Token: 0x04000419 RID: 1049
		internal readonly TableInformation[] table_infos = new TableInformation[58];

		// Token: 0x0400041A RID: 1050
		internal readonly MetadataTable[] tables = new MetadataTable[58];

		// Token: 0x0400041B RID: 1051
		private bool large_string;

		// Token: 0x0400041C RID: 1052
		private bool large_blob;

		// Token: 0x0400041D RID: 1053
		private bool large_guid;

		// Token: 0x0400041E RID: 1054
		private readonly int[] coded_index_sizes = new int[14];

		// Token: 0x0400041F RID: 1055
		private readonly Func<Table, int> counter;

		// Token: 0x04000420 RID: 1056
		internal uint[] string_offsets;
	}
}
